//
//  BEDateExtension.swift
//  BasicExtensions
//
//  Created by Fanxx on 2018/3/23.
//  Copyright © 2018年 fanxx. All rights reserved.
//

import Foundation

///日期单位
public enum BEDateUnit: Int, Comparable {
    ///年
    case year = 6
    ///月
    case month = 5
    ///日
    case day = 4
    ///时
    case hour = 3
    ///分
    case minute = 2
    ///秒
    case second = 1
    ///毫秒
    case nanosecond = 0
    public static func < (lhs: BEDateUnit, rhs: BEDateUnit) -> Bool {
        return lhs.rawValue < rhs.rawValue
    }
}
/// 日期值
public struct BEDateValue {
    ///单位
    public let unit: BEDateUnit
    ///值
    public let value: Int
    ///年
    public static func year(_ value: Int) -> Self {
        return .init(unit: .year, value: value)
    }
    ///月
    public static func month(_ value: Int) -> Self {
        return .init(unit: .month, value: value)
    }
    ///日
    public static func day(_ value: Int) -> Self {
        return .init(unit: .day, value: value)
    }
    ///时
    public static func hour(_ value: Int) -> Self {
        return .init(unit: .hour, value: value)
    }
    ///分
    public static func minute(_ value: Int) -> Self {
        return .init(unit: .minute, value: value)
    }
    ///秒
    public static func second(_ value: Int) -> Self {
        return .init(unit: .second, value: value)
    }
    ///毫秒
    public static func nanosecond(_ value: Int) -> Self {
        return .init(unit: .nanosecond, value: value)
    }
}
///常用格式化参数
public struct BEDateFormat: ExpressibleByStringLiteral {
    public typealias StringLiteralType = String
    
    public let rawValue: String
    
    public init(stringLiteral rawValue: String) {
        self.rawValue = rawValue
    }
    
    public var date: Self { return "yyyy-MM-dd" }
    public var time: Self { return "HH:mm:ss" }
    public var datetime: Self { return "yyyy-MM-dd HH:mm:ss" }
    public var utc: Self { return "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" }
    //    public var utc2: Self { return "yyyy-MM-dd'T'HH:mm:ssXXX" }
}

extension Date {
    ///实例
    public static func create(_ values: BEDateValue...) -> Date {
        var components = DateComponents()
        for value in values {
            switch value.unit {
            case .year: components.year = value.value
            case .month: components.month = value.value
            case .day: components.day = value.value
            case .hour: components.hour = value.value
            case .minute: components.minute = value.value
            case .second: components.second = value.value
            case .nanosecond: components.nanosecond = value.value
            }
        }
        return Calendar.current.date(from: components)!
    }
    public func format(_ format: String = "yyyy-MM-dd HH:mm:ss", timeZone: TimeZone? = nil, locale: Locale? = .current) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = format
        if let tz = timeZone {
            formatter.timeZone = tz
        }
        formatter.locale = locale
        return formatter.string(from: self)
    }
    public func format(_ format: BEDateFormat) -> String {
        return self.format(format.rawValue)
    }
    ///两个日期相差
    public func timeIntervalSince(_ date: Date, for unit: BEDateUnit) -> Int {
        switch unit {
        case .nanosecond: return Int(self.timeIntervalSince(date) * 1000)
        case .second: return Int(self.timeIntervalSince(date))
        case .minute: return Int(self.timeIntervalSince(date) / 60)
        case .hour: return Int(self.timeIntervalSince(date) / 60 / 60)
        case .day:
            let comp = Set<Calendar.Component>(arrayLiteral: Calendar.Component.day)
            return Calendar.current.dateComponents(comp, from: date, to: self).day ?? 0
        case .month:
            let comp = Set<Calendar.Component>(arrayLiteral: Calendar.Component.month)
            return Calendar.current.dateComponents(comp, from: date, to: self).month ?? 0
        case .year:
            let comp = Set<Calendar.Component>(arrayLiteral: Calendar.Component.year)
            return Calendar.current.dateComponents(comp, from: date, to: self).year ?? 0
        }
    }
    ///距离现在隔了多久
    public func timeIntervalSinceNow(for unit: BEDateUnit) -> Int {
        return self.timeIntervalSince(Date(), for: unit)
    }
}
extension TimeInterval {
    ///将秒显示为天时分秒的剩余时长描述，max至少为天, least代表固定会出现的单位，若高于least的单位值为0时不出现
    public func countdownDescription(at least: BEDateUnit = .hour, min: BEDateUnit = .minute, max: BEDateUnit = .day, end endDesc:String = "已结束") -> String {
        let timeString = NSMutableString()
        var time = self
        if time > 0 {
            let day = Int(time / 24 / 60 / 60)
            time = time - Double(day * 24 * 60 * 60)
            let hour = Int(time / 60 / 60)
            time = time - Double(hour * 60 * 60)
            let minute = Int(time / 60)
            time = time - Double(minute * 60)
            let second = Int(time)
            time = time - Double(second)
            let nanosecond = Int(time * 1000)
            
            if max >= .day {
                if day > 0 {
                    timeString.append("\(day)天")
                }else if least >= .day{
                    timeString.append("0天")
                }
            }
            if max >= .hour && min <= .hour {
                if hour > 0 {
                    timeString.append(hour >= 10 ? "\(hour)时" : "0\(hour)时")
                }else if least >= .hour {
                    timeString.append("00时")
                }
            }
            if max >= .minute && min <= .minute {
                if minute > 0 {
                    timeString.append(minute >= 10 ? "\(minute)分" : "0\(minute)分")
                }else if least >= .minute {
                    timeString.append("00分")
                }
            }
            if max >= .second && min <= .second {
                if second > 0 {
                    timeString.append(second >= 10 ? "\(second)秒" : "0\(second)秒")
                }else if least >= .second {
                    timeString.append("00秒")
                }
            }
            if max >= .nanosecond && min <= .nanosecond {
                if nanosecond > 100 {
                    timeString.append("\(nanosecond)毫秒")
                }else if nanosecond > 10 {
                    timeString.append("0\(nanosecond)毫秒")
                }else if nanosecond > 0 {
                    timeString.append("00\(nanosecond)毫秒")
                }else if least >= .nanosecond {
                    timeString.append("000毫秒")
                }
            }
        }else{
            timeString.append(endDesc)
        }
        return timeString as String
    }
    ///转为时：分：秒的显示格式
    public func timeDescription(inChinese: Bool = false) -> String {
        let timeString = NSMutableString()
        var time = self
        let separators = inChinese ? ["小时","分","秒"] : [":",":",""]
        if time > 0 {
            let hour = Int(time / 60 / 60)
            time = time - Double(hour * 60 * 60)
            let minute = Int(time / 60)
            time = time - Double(minute * 60)
            let second = Int(time)
            time = time - Double(second)
            //            let nanosecond = Int(time * 1000)
            if hour > 0 {
                if inChinese {
                    timeString.append("\(hour)\(separators[0])")
                }else{
                    timeString.append(hour >= 10 ? "\(hour)\(separators[0])" : "0\(hour)\(separators[0])")
                }
            }
            if minute > 0 {
                timeString.append(minute >= 10 ? "\(minute)\(separators[1])" : "0\(minute)\(separators[1])")
            }else {
                timeString.append("00\(separators[1])")
            }
            if second > 0 {
                timeString.append(second >= 10 ? "\(second)\(separators[2])" : "0\(second)\(separators[2])")
            }else {
                timeString.append("00\(separators[2])")
            }
        }else{
            timeString.append("00\(separators[1])00\(separators[2])")
        }
        return timeString as String
    }
}

extension DispatchTimeInterval {
    /// 转为TimeInterval数值
    func asTimeInterval() -> TimeInterval {
        switch self {
        case .never: return .infinity
        case .seconds(let value): return .init(value)
        case .milliseconds(let value): return .init(value) / 1000
        case .microseconds(let value): return .init(value) / 1000000
        case .nanoseconds(let value): return .init(value) / 1000000000
        @unknown default:
            fatalError()
        }
    }
}
